/*
 * ContactManager.cpp
 *
 *  Created on: Jan 25, 2015
 *      Author: wasp
 */


#include <bb/pim/contacts/Contact>
#include <bb/pim/contacts/ContactService>
#include <bb/pim/contacts/ContactListFilters>
#include <bb/cascades/ItemGrouping>
#include <bb/data/SqlConnection>
#include <bb/data/DataAccessError>
#include <bb/data/SqlDataAccess>
#include "ContactManager.hpp"
#include "../applicationui.hpp"

using namespace bb::cascades;
using namespace bb::pim::contacts;

namespace de
{
    namespace heimweghelden
    {
        namespace user
        {
            const QString DB_PATH = "./data/heimweghelden.db";
            ContactManager::ContactManager(QObject* parent) :
                QObject(parent),
                app(reinterpret_cast<ApplicationUI*>(parent)),
                _contactService(new ContactService(this)),
                _contacts(new bb::cascades::GroupDataModel())
            {
                QSqlDatabase database = QSqlDatabase::addDatabase("QSQLITE");
                database.setDatabaseName(DB_PATH);
                if (database.open()) {
                    database.close();
                    sqlConnection = new bb::data::SqlConnection("./data/heimweghelden.db");
                    initDb();
                    initContacts();
                }
                else {
                    app->alert("Opening database failed", true);
                }

                // Add the entry to the model
                QStringList sortkeys;
                sortkeys.append("negfavourite");
                sortkeys.append("name");
                _contacts->setSortingKeys(sortkeys);
                _contacts->setSortedAscending(true);
                _contacts->setGrouping(ItemGrouping::None);
            }

            ContactManager::~ContactManager() {
                sqlConnection->deleteLater();
            }

            void ContactManager::initDb() {
                QSqlDatabase database = QSqlDatabase::database();
                if ( ! database.isOpen()) {
                    if ( ! database.open()) {
                        return;
                    }
                }
                const QString createSQL = "CREATE TABLE IF NOT EXISTS contacts ( "
                                          "                phone VARCHAR PRIMARY KEY, "
                                          "                name VARCHAR,"
                                          "                hhid VARCHAR,"
                                          "                favourite INTEGER"
                                          ");";


                QSqlQuery query(database);
                if ( ! query.exec(createSQL)) {
                    const QSqlError error = query.lastError();
                    app->alert(tr("Create table error: %1").arg(error.text()), true);
                    return;
                }

                bb::data::SqlDataAccess *sqlda = new bb::data::SqlDataAccess(DB_PATH);
                const QString sql = "select count(phone) as n from contacts";
                QVariant result = sqlda->execute(sql);
                if (sqlda->hasError()) {
                    app->alert(tr("Get contact count error: %1").arg(sqlda->error().errorMessage()), true);
                    delete sqlda;
                    return;
                }
                int contactscount = 0;
                // The data will be displayed in a group data model
                // Clear any previous reads from the data model first
                if( !result.isNull() ) {
                    QVariantList list = result.value<QVariantList>();
                    if (list.size() == 1) {
                        QVariantMap map = list.at(0).value<QVariantMap>();
                        contactscount = map.value("n").value<int>();
                    }
                }
                delete sqlda;
                if (contactscount != 0) {
                    return;
                }
                loadPhoneContacts();
            }

            void ContactManager::initContacts() {
                _contacts->setGrouping(ItemGrouping::ByFirstChar);
                bool ok = connect(_contactService, SIGNAL(contactsAdded(QList<int>)), SLOT(fillContactModel()));
                Q_ASSERT(ok);
                ok = connect(_contactService, SIGNAL(contactsChanged(QList<int>)), SLOT(fillContactModel()));
                Q_ASSERT(ok);
                ok = connect(_contactService, SIGNAL(contactsDeleted(QList<int>)), SLOT(fillContactModel()));
                Q_ASSERT(ok);

                // Fill the data model with contacts initially
                fillContactModel();
            }
            void ContactManager::fillContactModel()
            {
                // Clear the old contact information from the model
                _contacts->clear();

                bb::data::SqlDataAccess *sqlda = new bb::data::SqlDataAccess(DB_PATH);
                const QString sql = "select * from contacts";
                QVariant result = sqlda->execute(sql);
                if (sqlda->hasError()) {
                    qDebug() << "" << sqlda->error().errorMessage();
                    delete sqlda;
                    return;
                }
                if( !result.isNull() ) {
                    QVariantList datalist;
                    QVariantList list = result.value<QVariantList>();
                    foreach(const QVariant e, list) {
                        QVariantMap item = e.value<QVariantMap>();
                        item.insert("negfavourite", item.value("favourite").value<int>() == 1 ? 0 : 1);
                        datalist.append(item);
                    }
                    _contacts->insertList(datalist);
                }
                delete sqlda;
            }

            void ContactManager::loadPhoneContacts() {
                //TODO: das sollte in einem eigenem thread passieren

                ContactListFilters filter;
                filter.setLimit(1000);
                filter.setHasAttribute(AttributeKind::Phone);
                filter.setSortBy(SortColumn::FirstName, SortOrder::Descending);
                QList<Contact> contacts = _contactService->contacts(filter);

                QList<QVariantMap> contactlist;
                QHash<QString, QVariantMap> numbers;
                foreach (const Contact &idContact, contacts) {
                    foreach(const ContactAttribute &number, idContact.phoneNumbers()) {
                        QString n = number.value();
                        QVariantMap entry;
                        //entry["contactId"] = idContact.id();
                        entry["displayName"] = idContact.displayName();
                        //entry["firstName"] = idContact.firstName();
                        //entry["lastName"] = idContact.lastName();
                        entry["favourite"] = idContact.isFavourite();
                        entry["number"] = n;
                        numbers[n] = entry;
                    }
                }
                contactlist = checkListForHelden(numbers.values());
                bb::data::SqlDataAccess *sqlda = new bb::data::SqlDataAccess(DB_PATH);
                foreach(const QVariantMap item, contactlist) {
                    int fav = item.value("favourite").value<bool>() ? 1 : 0;
                    QVariantList contact;
                        contact
                            << item.value("phone").value<QString>()
                            << item.value("name").value<QString>()
                            << item.value("hhid").value<QString>()
                            << fav;
                        sqlda->execute("INSERT INTO contacts"
                                      "    (phone, name, hhid, favourite) "
                                      "    VALUES (:phone, :name, :hhid, :favourite)", contact);
                        if(!sqlda->hasError()) {
                            qDebug() << "SUCCESS beim einsetzen";
                        } else {
                            qDebug() << "ERROR beim einsetzen" << sqlda->error().errorMessage();
                        }
                }
                delete sqlda;


            }

            bb::cascades::GroupDataModel* ContactManager::contacts() const {
                return _contacts;
            }

            /*void ContactManager::bindModel(bb::cascades::GroupDataModel* m) {
                if (m == _contacts)
                    return;
                _contacts = m;
                initContacts();
            }*/
            QList<QVariantMap> ContactManager::checkListForHelden(QList<QVariantMap> input) {
                QList<QVariantMap> output;
                //TODO: muss an den server gesendet werden. alles nur dummy hier
                foreach(const QVariantMap item, input) {
                    QString number = item.value("number").value<QString>();
                    if (number == "+491783200590" || number == "+4917687414641") {
                        QVariantMap data;
                        data.insert("phone", number);
                        data.insert("name", item.value("displayName").value<QString>());
                        data.insert("favourite", item.value("favourite").value<bool>());
                        data.insert("hhid", "");
                        output.push_back(data);
                    }
                }
                return output;
            }

            void ContactManager::contactFavouriteChanged(QString number, bool favourite) {
                bb::data::SqlDataAccess *sqlda = new bb::data::SqlDataAccess(DB_PATH);
                const QString sqlCommand = "UPDATE contacts "
                                           "    SET favourite = :favourite"
                                           "    WHERE phone = :phone";
                QVariantMap bindings;
                bindings["favourite"] = favourite ? 1 : 0;
                bindings["phone"] = number;

                sqlda->execute(sqlCommand, bindings);
                if (sqlda->hasError()) {
                    qDebug() << QString("SQL error: %1").arg(sqlda->error().errorMessage());
                }
                fillContactModel();
            }
        } /* namespace user */
    } /* namespace heimweghelden */
} /* namespace de */
